﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using Epsilon.Parse;
using Epsilon.Expr;
using Epsilon.Typing;
using Epsilon.Output;

namespace Epsilon
{
    class Program
    {
        static void Main(string[] args)
        {
            if (args.Length < 2)
            {
                Usage();
                return;
            }

#if DEBUG
            try
            {
#endif
            List<string> files = new List<string>();
            for (int i = 0; i < args.Length - 1; i++)
                files.Add(args[i]);
            Process(files, args[args.Length - 1]);
#if DEBUG
            }
            catch (Exception e)
            {
                Console.WriteLine();
                Console.WriteLine(e.Message);
            }
#endif
        }

        static void Process(List<string> file, string main)
        {
            List<Process> processes = new List<Process>();
            long start, end;

            foreach (string f in file)
            {
                Console.WriteLine("Processing file " + f);
                StreamReader reader = new StreamReader(f);

                Console.WriteLine("Starting lexing");
                start = DateTime.Now.Ticks;
                List<Token> tokens = Lexer.Lex(reader);
                end = DateTime.Now.Ticks;
                Console.WriteLine("Lexing finished in " + ((end - start)/10000).ToString() + " ms");
                Console.WriteLine();

                Console.WriteLine("Starting parsing");
                start = DateTime.Now.Ticks;
                Parser p = new Parser(tokens, f);
                processes.Add(p.Parse());
                end = DateTime.Now.Ticks;
                Console.WriteLine("Parsing finished in " + ((end - start)/10000).ToString() + " ms");
                Console.WriteLine();
            }

            Console.WriteLine("Starting type checking");
            start = DateTime.Now.Ticks;
            GlobalTypeChecker typer = new GlobalTypeChecker(processes);
            typer.TypeCheck();
            end = DateTime.Now.Ticks;
            Console.WriteLine("Type checking finished in " + ((end - start)/10000).ToString() + " ms");
            Console.WriteLine();
            Console.WriteLine("Program has been verified as secure");
            Console.WriteLine();
            Console.WriteLine("Starting output routine");
            start = DateTime.Now.Ticks;
            ProgramWriter op = new ProgramWriter(processes, main);
            op.WriteFiles();
            end = DateTime.Now.Ticks;
            Console.WriteLine("Output routine finished in " + ((end - start) / 10000).ToString() + " ms");
        }

        static void Usage()
        {
            Console.WriteLine("Error: too few arguments");
            Console.WriteLine();
            Console.WriteLine("Usage:");
            Console.WriteLine("epsilon <input file 1> ... <input file n> <output file>");
            Console.WriteLine();
        }
    }
}
